package com.atguigu.gmall.filter;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.common.result.Result;
import com.atguigu.gmall.common.result.ResultCodeEnum;
import com.atguigu.gmall.common.util.IpUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpCookie;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.List;


@Component
public class AuthGlobalFilter implements GlobalFilter {

    @Autowired
    private RedisTemplate redisTemplate;

    @Value("${authUrls.url}")
    private String authUrl;

    private AntPathMatcher antPathMatcher = new AntPathMatcher();

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //获取请求
        ServerHttpRequest request = exchange.getRequest();
        //获取请求的url
        String path = request.getURI().getPath();

        //判断用户是否访问内部数据接口
        if (antPathMatcher.match("/**/inner/**", path)) {
            //说明正在访问
            ServerHttpResponse response = exchange.getResponse();
            return out(response, ResultCodeEnum.PERMISSION);
        }

        //判断用户是否访问带有/auth的
        String userId = getUserId(request);

        if ("-1".equals(userId)) {
            //获取响应对象
            ServerHttpResponse response = exchange.getResponse();
            return out(response, ResultCodeEnum.PERMISSION);
        }

        if (antPathMatcher.match("/api/**/auth/**", path)) {
            if (StringUtils.isEmpty(userId)) {
                ServerHttpResponse response = exchange.getResponse();
                return out(response, ResultCodeEnum.LOGIN_AUTH);
            }
        }

        //判断用户访问的是哪个控制器 如果是黑名单的 停止访问 提示登录
        String[] split = authUrl.split(",");
        if (split != null && split.length > 0) {
            for (String url : split) {
                //包含上述url且用户id为空 则让其登录
                if (path.indexOf(url) != -1 && StringUtils.isEmpty(userId)) {
                    ServerHttpResponse response = exchange.getResponse();
                    //设置重定向参数
                    response.setStatusCode(HttpStatus.SEE_OTHER);

                    //重定向url地址
//                    response.getHeaders().set(HttpHeaders.LOCATION, "http://passport.gmall.com/login.html?originUrl=" + request.getURI());
                    response.getHeaders().set(HttpHeaders.LOCATION,"http://passport.gmall.com/login.html?originUrl="+request.getURI());
                    //设置重定向
                    return response.setComplete();
                }

            }
        }

        //把用户id设置到请求头中 传递给后台微服务

        if (!StringUtils.isEmpty(userId)) {
            //设置请求头
            request.mutate().header("userId", userId).build();

            //返回数据
            return chain.filter(exchange.mutate().request(request).build());
        }
        //默认返回
        return chain.filter(exchange);
    }


    /**
     * 获取用户id
     *
     * @param request
     * @return
     */
    private String getUserId(ServerHttpRequest request) {
        String token = "";
        //从请求头中获取token
        List<String> stringList = request.getHeaders().get("token");
        if (!CollectionUtils.isEmpty(stringList)) {
            token = stringList.get(0);
        } else {
            //从cookie中获取token
            HttpCookie httpCookie = request.getCookies().getFirst("token");
            if (httpCookie != null) {
                token = httpCookie.getValue();
            }
        }
        //判断token不为空
        if (!StringUtils.isEmpty(token)) {
            //  登录key
            String loginKey = "user:login:" + token;

            //从缓存中获取数据
            String strJson = (String) redisTemplate.opsForValue().get(loginKey);
            JSONObject jsonObject = JSONObject.parseObject(strJson);
            if (jsonObject != null) {
                //从缓存中获取ip地址
                String ip = (String) jsonObject.get("ip");
                if (ip.equals(IpUtil.getGatwayIpAddress(request))) {
                    String userId = (String) jsonObject.get("userId");
                    return userId;
                }else {
                    return "-1";
                }

            }
        }
        return "";
    }

    /**
     * 用户提示方法
     *
     * @param response
     * @param resultCodeEnum
     * @return
     */
    private Mono<Void> out(ServerHttpResponse response, ResultCodeEnum resultCodeEnum) {
        //输入的信息是result
        Result<Object> result = Result.build(null, resultCodeEnum);
        //把result转换为string 或字节数组
        String jsonString = JSON.toJSONString(result);
        //设置字符编码
        response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
        //  输出result 对象数据！
        DataBuffer wrap = response.bufferFactory().wrap(jsonString.getBytes());
        //  输出数据！
        return response.writeWith(Mono.just(wrap));
    }
}
